import os
import time
import requests
from celery.utils.log import get_task_logger
from config.const import Const
from models.silo import Message, MassLog, Group
from utils.query import get_openid_list
from utils.decorators import with_application
from extensions import db
from json import JSONDecodeError
from kombu import Exchange, Queue
from .producter import product_worker
from utils.mock import mock_wechat_callback
from . import app

DING_TALK_ALARM_URL = os.getenv('DING_TALK_ALARM_URL')

logger = get_task_logger(__name__)


@app.task
def ding_alarm(msg):
    """发送到钉钉报警群"""
    if Const.ENV in ('test', 'prod'):
        r = requests.post(DING_TALK_ALARM_URL, json={'msgtype': 'text', 'text': {'content': msg}})
        logger.info(f'status_code: {r.status_code}, content: {r.content}')


@app.task
@with_application
def wx_app_forward(msg_id, task_has_group_msg_id, query_sql, test_mode):
    """
    微信公众号群发任务
    :param msg_id: 要群发的消息id
    :param query_sql: 查询群组人数sql
    :param task_has_group_msg_id: 任务与推送对象与消息的关系表id
    """
    db.session.close()
    
    message = Message.query.get(msg_id)
    app_id, openid_list = get_openid_list(query_sql)
    if message.msg_type != 'text':
        raise NotImplementedError
    
    # 循环调用群发接口
    length = len(openid_list)
    for index in range(0, length, 10000):
        wx_app_mass_text.delay(message.content, openid_list[index:index+10000],
                               task_has_group_msg_id, app_id, test_mode)
    logger.info('任务群发人数: {}'.format(length))
    

@app.task
@with_application
def wx_app_mass_text(content, openid_list, task_has_group_msg_id, app_id, test_mode):
    
    db.session.close()
    logger.info('群发公众号: {}'.format(app_id))
    logger.info('群发人数: {}'.format(len(openid_list)))
    logger.info('群发消息: {}'.format(content))
    data = {
        "content": content,
        "app_id": app_id,
        "group_or_users": openid_list,
    }
    if test_mode:
        # 模拟模拟
        mass_log = MassLog(
            task_has_group_msg_id=task_has_group_msg_id,
            # wx_msg_id=0,
            state=' test send job submission success',
        )
        db.session.add(mass_log)
        db.session.flush()
        mass_log.wx_msg_id = mass_log.id
        db.session.commit()
        # 向mq抛出数据
        queue = Queue(name='silo', exchange=Exchange(name='micro-events', type='topic'),
                      routing_key='silo.daemon.backend.mass')
        data = mock_wechat_callback(wx_msg_id=mass_log.wx_msg_id, totalcount=len(openid_list))
        product_worker(queue=queue, data=data)
        return 'test_mode'

    res = requests.post(url=Const.MASS_TEXT_URL, json=data)
    try:
        r = res.json()
    except JSONDecodeError:
        logger.info(res.status_code)
        return
    
    logger.info(r)
    mass_log = MassLog(
        task_has_group_msg_id=task_has_group_msg_id,
        wx_msg_id=r['msg_id'],
        state=r['errmsg']
    )
    mass_log.save()
    return r


@app.task
@with_application
def update_total_count(query_sql, group_id):
    """更新群组的 total count"""
    db.session.close()
    
    query_sql = query_sql.replace(';', '')
    sql = 'select count(1) from ({}) as tmp'.format(query_sql)
    logger.info('\n获取查询集的总数sql:\n{}\n'.format(sql))

    total_count = db.session.execute(sql).scalar()

    try:
        total_count = db.session.execute(sql).scalar()
    except Exception as e:
        db.session.rollback()

    group = Group.query.get(group_id)
    if not group:
        # 应对生产环境的主从延迟
        time.sleep(0.5)
    group = Group.query.get(group_id)
    if not group:
        return {'msg': '不存在的group_id: {}'.format(group_id)}
    
    # 存在父组的情况
    if group.parent_id != 0:
        parent_group = Group.query.with_for_update(of=Group.total_count).get(group.parent_id)
        parent_group.total_count += total_count
        logger.info('父组 {} total_count加上: {}'.format(parent_group.title, total_count))
    logger.info('更新非父组 {} total_count为{}'.format(group.title, total_count))
    group.total_count = total_count
    db.session.commit()
